#if PocketPC
using System;
using System.Text;
using GeoFramework.IO.Serial;

namespace GeoFramework.IO.HewlettPackard
{
    /// <summary>
    /// Indicates the model of iPAQ device with integrated GPS support.
    /// </summary>
    public enum IpaqDeviceModel
    {
        /// <summary>
        /// The device could not be identified as an iPAQ device with integrated GPS.
        /// </summary>
        Unknown,
        /// <summary>
        /// The device is a Hewlett-Packard HW6510.
        /// </summary>
        HW6510,
        /// <summary>
        /// The device is a Hewlett-Packard HW6515.
        /// </summary>
        HW6515
    }

    /// <summary>
    /// Represents device-specific information about Hewlett-Packard hand-held devices.
    /// </summary>
    /// <remarks><para>Hewlett-Packard manufacturs some hand-held devices which include integrated
    /// GPS devices.  For such devices, GPS.NET supports the ability to detect these devices
    /// in order to deliver the best performance.  This class contains features supported by
    /// the HP HW6510 and HP HW6515.</para>
    /// <para>Members of this class will throw an exception if they are called on a device which
    /// is not an iPAQ.  Check the DeviceModel property to ensure that the device is recognized before 
    /// attempting to access other members of this class.</para></remarks>
    public 
#if Framework20
	static
#else
	sealed
#endif
		class Ipaq
    {
        private const int iPAQ_SUCCESS = 1;
        private const int iPAQ_MAX_ID = 20;
        private const int iPAQ_ON = 1;
        private const int iPAQ_OFF = 0;

        private static IpaqDeviceModel pDeviceModel = IpaqDeviceModel.Unknown;
        private static SerialDevice pIntegratedGpsDevice;
        private static bool pIsSupported;
        private static bool pIsIntegratedGpsDeviceAllowed = true;

        // This class cannot be created.
        //private Ipaq()
        //{
        //}

        /// <summary>
        /// Creates a new instance.
        /// </summary>
        /// <remarks>
        /// During this constructor, the local device is analyzed in an attempt to 
        /// identify it as an iPAQ device with integrated GPS support.
        /// </remarks>
        static Ipaq()
        {
            // If we're running on the desktop, don't even try to look for iPAQ information
            if (Environment.OSVersion.Platform != PlatformID.WinCE)
                return;

			// Is it supported?
			try
			{
				if(!System.IO.File.Exists(@"\Windows\iPAQUTIL.dll"))
					return;
			}
			catch
			{
				// Not supported!
				return;
			}

            try
            {
                // Get the current model ID
                StringBuilder model = new StringBuilder(iPAQ_MAX_ID);
                if(NativeMethods.iPAQGetModelID(model) == iPAQ_SUCCESS)
                {
                    string ModelString = model.ToString();
                    if (ModelString.IndexOf("6510") != -1)
                    {
                        pIsSupported = true;
                        pDeviceModel = IpaqDeviceModel.HW6510;
                        pIntegratedGpsDevice = new SerialDevice(CommunicationPort.Com7, BaudRate.Baud57600);
                        pIntegratedGpsDevice.SetProtocol(GeoFramework.Gps.Nmea.NmeaInterpreter.ProtocolName);
                    }
                    else if (ModelString.IndexOf("6515") != -1)
                    {
                        pIsSupported = true;
                        pDeviceModel = IpaqDeviceModel.HW6515;
                        pIntegratedGpsDevice = new SerialDevice(CommunicationPort.Com7, BaudRate.Baud57600);
                        pIntegratedGpsDevice.SetProtocol(GeoFramework.Gps.Nmea.NmeaInterpreter.ProtocolName);
                    }
                }
            }
            catch
            {
                // Ignore.. probably not an IPAQ device
            }
        }

        /// <summary>
        /// Returns the model of Hewlett-Packard iPAQ device.
        /// </summary>
        public static IpaqDeviceModel DeviceModel
        {
            get
            {
                return pDeviceModel;
            }           
        }

        /// <summary>
        /// Returns the communication port of the integrated GPS device.
        /// </summary>
        public static SerialDevice IntegratedGpsDevice
        {
            get
            {
                return pIntegratedGpsDevice;
            }
        }

        /// <summary>
        /// Returns whether an integrated GPS device is present for this iPAQ device.
        /// </summary>
        public static bool IsSupported
        {
            get
            {
                return pIsSupported;
            }
        }

        /// <summary>
        /// Controls whether the built-in GPS devices can be used or not.
        /// </summary>
        /// <remarks>In some cases (such as the Hewlett-Packard HW651x), the internal GPS device
        /// may not be sufficient for some users.  Setting this property to <strong>False</strong>
        /// causes the integrated GPS device to be ignored during device detection.  This property
        /// defaults to <strong>True</strong> since built-in devices should almost always be preferred.</remarks>
        public static bool IsIntegratedGpsDeviceAllowed
        {
            get
            {
                return pIsIntegratedGpsDeviceAllowed;
            }
            set
            {
                pIsIntegratedGpsDeviceAllowed = value;
            }
        }

        /// <summary>
        /// Returns a percentage indicating the remaining battery life of the device.
        /// </summary>
        public static int BatteryStrength
        {
            get
            {
                int pBatteryLevel = 0;
                if (NativeMethods.iPAQGetMainBatteryLevel(ref pBatteryLevel) == iPAQ_SUCCESS)
                    return pBatteryLevel;
                // Remaining battery strength is not supported
                throw new NotSupportedException("This device does not support the ability to return battery strength.");
            }
        }

        /// <summary>
        /// Controls whether the Bluetooth radio is currently enabled.
        /// </summary>
        public static bool IsBluetoothEnabled
        {
            get
            {
                Int32 Result = 0;
                if(NativeMethods.iPAQGetBlueToothRadioStatus(ref Result) == iPAQ_SUCCESS)
                    return Result == 1;
                else
                    return false;
            }
            set
            {
                Int32 Result = (value ? 1 : 0);
                if (NativeMethods.iPAQSetBlueToothRadio(ref Result) == iPAQ_SUCCESS)
                    return;
                throw new NotSupportedException("This device does not support the ability to enable or disable the Bluetooth radio.");
            }
        }

        /// <summary>
        /// Controls the amount of seconds before the device is allowed to suspend itself in order to conserve power.
        /// </summary>
        public static TimeSpan DeviceSuspendTimeout
        {
            get
            {
                Int32 pTimeOutSeconds = 0;
                if (NativeMethods.iPAQGetOnBatteryDeviceSuspendTimeOut(ref pTimeOutSeconds) == iPAQ_SUCCESS)
                    return TimeSpan.FromSeconds(pTimeOutSeconds);
                // No timeout is supported
                throw new NotSupportedException("This device does not support control of device suspend timeouts.");
            }
            set
            {
                // Convert the timeout to seconds
                Int32 pTimeOutSeconds = Convert.ToInt32(value.TotalSeconds);
                // Now set it on the device
                if (NativeMethods.iPAQSetOnBatteryDeviceSuspendTimeOut(ref pTimeOutSeconds) == iPAQ_SUCCESS)
                    return;
                // This feature is not supported.
                throw new NotSupportedException("This device does not support control of device suspend timeouts.");
            }
        }
    }
}
#endif